#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
项目创建命令
"""

import os
import shutil
from argparse import Namespace

from ..core.logger import Log


class ProjectCreatorCommand:

    def __init__(self):
        self.log = Log()

    def execute(self, args: Namespace) -> int:
        """
        执行项目创建命令
        
        Args:
            args: 命令行参数
            
        Returns:
            int: 退出码，0表示成功，非0表示失败
        """
        try:
            project_name = args.project_name
            template = getattr(args, 'template', 'basic')
            with_docker = getattr(args, 'with_docker', False)

            # 检查项目目录是否已存在
            if os.path.exists(project_name):
                self.log.error(f"项目目录已存在: {project_name}")
                return 1

            self.log.info(f"开始创建项目: {project_name}")
            self.log.info(f"使用模板: {template}")

            # 创建项目结构
            self._create_project_structure(project_name, template, with_docker)

            self.log.success("项目创建完成!")
            self.log.info(f"项目路径: {os.path.abspath(project_name)}")
            self.log.info("下一步:")
            self.log.info(f"  cd {project_name}")
            self.log.info(f"  pip install -r requirements.txt")
            self.log.info(f"  pytest")

            return 0

        except Exception as e:
            self.log.error(f"创建项目时发生错误: {e}")
            return 1

    def create_config_file(self, target_dir: str = ".") -> int:
        """
        在指定目录创建配置文件
        
        Args:
            target_dir: 目标目录，默认为当前目录
            
        Returns:
            int: 退出码，0表示成功，非0表示失败
        """
        try:
            config_file_path = os.path.join(target_dir, "application.yaml")

            # 检查配置文件是否已存在
            if os.path.exists(config_file_path):
                self.log.warning(f"配置文件已存在: {config_file_path}")
                response = input("是否覆盖现有配置文件? (y/N): ")
                if response.lower() not in ['y', 'yes']:
                    self.log.info("操作已取消")
                    return 0

            # 查找模板文件
            template_path = self._find_template_file()
            if template_path and os.path.exists(template_path):
                # 复制模板文件
                shutil.copy2(template_path, config_file_path)
                self.log.success(f"配置文件创建成功: {config_file_path}")
            else:
                # 使用内置模板创建
                self._create_config_from_builtin_template(config_file_path)
                self.log.success(f"配置文件创建成功: {config_file_path}")

            self.log.info("请根据实际情况修改配置文件中的参数")
            self.log.info(f"配置文件路径: {os.path.abspath(config_file_path)}")

            return 0

        except Exception as e:
            self.log.error(f"创建配置文件时发生错误: {e}")
            return 1

    def _find_template_file(self) -> str:
        """
        查找配置文件模板
        
        Returns:
            str: 模板文件路径，如果未找到则返回None
        """
        # 获取当前文件所在目录的上级目录
        current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        template_path = os.path.join(current_dir, "templates", "application.yaml.template")
        return template_path if os.path.exists(template_path) else None

    def _create_config_from_builtin_template(self, config_file_path: str):
        """
        使用内置模板创建配置文件
        
        Args:
            config_file_path: 配置文件路径
        """
        application_yaml_content = """# PyAssured API 测试框架配置文件

# API 服务器配置
host:
  dev: "https://api-dev.example.com"     # 开发环境
  test: "https://api-test.example.com"   # 测试环境
  prod: "https://api.example.com"        # 生产环境

# 请求头配置
headers:
  Content-Type: "application/json"
  User-Agent: "PyAssured-TestFramework/1.0"
  # Authorization: "Bearer your-token-here"  # 如需要认证，取消注释并填入token

# 数据库配置（可选）
dbconfig:
  dev:
    host: "localhost"
    port: 3306
    username: "dev_user"
    password: "dev_password"
    database: "dev_database"
  test:
    host: "test-db.example.com"
    port: 3306
    username: "test_user"
    password: "test_password"
    database: "test_database"
  prod:
    host: "prod-db.example.com"
    port: 3306
    username: "prod_user"
    password: "prod_password"
    database: "prod_database"

# 当前环境（dev/test/prod）
env: "dev"

# 调试模式
debugMode: true

# 请求超时设置（秒）
timeout: 30

# 重试配置
retry:
  max_attempts: 3
  delay: 1
  backoff_factor: 2
"""

        with open(config_file_path, 'w', encoding='utf-8') as f:
            f.write(application_yaml_content)

    def _create_project_structure(self, project_name: str, template: str, with_docker: bool):
        """
        创建项目目录结构
        
        Args:
            project_name: 项目名称
            template: 模板类型
            with_docker: 是否包含Docker配置
        """
        # 创建主目录
        os.makedirs(project_name)

        # 创建目录结构
        os.makedirs(os.path.join(project_name, 'api'), exist_ok=True)
        os.makedirs(os.path.join(project_name, 'tests'), exist_ok=True)
        os.makedirs(os.path.join(project_name, 'data'), exist_ok=True)
        os.makedirs(os.path.join(project_name, 'logs'), exist_ok=True)
        os.makedirs(os.path.join(project_name, 'report'), exist_ok=True)

        # 创建基本文件
        self._create_basic_files(project_name)

        # 根据模板创建额外文件
        # 目前只支持基础模板

        # 创建Docker配置
        if with_docker:
            self._create_docker_files(project_name)

    def _create_basic_files(self, project_name: str):
        # pytest.ini
        pytest_ini_content = """[pytest]
addopts = -s --alluredir report
testpaths = ./tests
python_files = test*.py
python_classes = Test*
python_functions = test*
log_format = %(asctime) s [%(filename) s:%(funcName)s:%(lineno)-2s] [%(levelname) 2s] %(message) s
log_date_format=%Y-%m-%d %H:%M:%S
disable_test_id_escaping_and_forfeit_all_rights_to_community_support=True
filterwarnings =
    error
    ignore::UserWarning
"""
        self._write_file(project_name, 'pytest.ini', pytest_ini_content)

        # conftest.py
        conftest_content = """#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytest
from pyassured.core.logger import Log
from pyassured.core.global_data import global_data

log = Log()

@pytest.fixture(scope="session", autouse=True)
def setup_test_environment():
    \"\"\"测试环境初始化\"\"\"
    log.info("🚀 开始执行测试")
    global_data.clear()
    yield
    log.info("✅ 测试执行完成")
"""

        # 创建 application.yaml (支持多环境配置)
        application_yaml_content = """# API服务地址配置 - 支持多环境
host:
  test: 'https://api-test.example.com'
  stg: 'https://api-stg.example.com'
  production: 'https://api.example.com'

# 请求头配置
headers:
  Content-Type: "application/json"
  User-Agent: "API-Test-Toolkit/1.0"

# 数据库配置 - 支持多环境
dbconfig:
  test:
    host: '127.0.0.1'
    port: '3306'
    user: 'test_user'
    pwd: 'test_password'
    dbName: 'test_db'
  stg:
    host: 'stg-db.example.com'
    port: '3306'
    user: 'stg_user'
    pwd: 'stg_password'
    dbName: 'stg_db'
  production:
    host: 'prod-db.example.com'
    port: '3306'
    user: 'prod_user'
    pwd: 'prod_password'
    dbName: 'prod_db'

# 当前环境 (可通过 TEST_ENV 环境变量覆盖)
env: test

# 调试模式
debugMode: False

# 请求超时配置（秒）
timeout: 30

# 重试配置
retry:
  max_attempts: 3  # 最大尝试次数（包含首次执行）
  delay: 1         # 重试间隔（秒）
"""
        self._write_file(project_name, 'conftest.py', conftest_content)
        self._write_file(project_name, 'application.yaml', application_yaml_content)

        # README.md
        readme_content = f"""# {project_name}

基于api-test-toolkit的API测试项目

## 项目结构

```
{project_name}/
├── api/          # API接口定义
├── tests/        # 测试用例
├── data/         # 测试数据
├── logs/         # 日志文件
├── report/       # 测试报告
├── conftest.py   # pytest配置
├── pytest.ini   # pytest设置
├── application.yaml  # 多环境配置文件
└── requirements.txt
```

## 快速开始

1. 安装依赖
```bash
pip install -r requirements.txt
```

2. 配置环境
编辑 `application.yaml` 文件，设置各环境的API地址和数据库连接信息

3. 运行测试
```bash
# 使用默认环境 (test)
pytest

# 或使用 apitest 命令
pax run

# 指定环境运行
pax run --env test
pax run --env stg
pax run --env production
```

4. 查看报告
```bash
allure serve report
```

## 环境配置说明

项目支持多环境配置，通过 `application.yaml` 文件管理：

- **host**: 不同环境的API服务地址
- **dbconfig**: 不同环境的数据库连接配置
- **env**: 默认环境 (可通过 TEST_ENV 环境变量覆盖)

### 环境切换方式

1. 命令行参数：`pax run --env <环境名>`
2. 环境变量：`set TEST_ENV=stg && pytest`
3. 配置文件：修改 `application.yaml` 中的 `env` 字段

优先级：命令行参数 > 环境变量 > 配置文件
"""
        self._write_file(project_name, 'README.md', readme_content)

        # 示例API文件
        api_example_content = """#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pyassured.core.base_api import BaseApi, Desc


@Desc("示例API")
class ExampleApi(BaseApi):
    \"\"\"示例API类\"\"\"
    
    path = "/api/example"
    method = "GET"
    
    def __init__(self):
        super().__init__()
"""
        self._write_file(project_name, 'api/__init__.py', '')
        self._write_file(project_name, 'api/example_api.py', api_example_content)

        # 示例测试文件
        test_example_content = """#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pytest
from api.example_api import ExampleApi


class TestExample:
    \"\"\"示例测试类\"\"\"
    
    @pytest.mark.smoke
    def test_example_api(self):
        \"\"\"示例测试用例\"\"\"
        response = ExampleApi().run()
        response.assert_that().status_code().should('equal_to', 200)
"""
        self._write_file(project_name, 'tests/__init__.py', '')
        self._write_file(project_name, 'tests/test_example.py', test_example_content)

        # requirements.txt
        requirements_content = """api-test-toolkit
pytest>=7.0.0
allure-pytest>=2.8.36
requests>=2.25.1
pyyaml>=5.4.1
pytest-json-report>=1.5.0
"""
        self._write_file(project_name, 'requirements.txt', requirements_content)

    def _create_docker_files(self, project_name: str):
        """创建Docker配置文件"""
        dockerfile_content = """FROM python:3.8-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["pytest"]
"""
        self._write_file(project_name, 'Dockerfile', dockerfile_content)

        docker_compose_content = """version: '3.8'

services:
  api-tests:
    build: .
    volumes:
      - ./report:/app/report
    environment:
      - TEST_ENV=test
"""
        self._write_file(project_name, 'docker-compose.yml', docker_compose_content)

    def _write_file(self, project_name: str, file_path: str, content: str):
        """写入文件"""
        full_path = os.path.join(project_name, file_path)
        os.makedirs(os.path.dirname(full_path), exist_ok=True)
        with open(full_path, 'w', encoding='utf-8') as f:
            f.write(content)
